package cn.com.netedge.iot.frontend.comm.nio;

import cn.com.netedge.iot.frontend.comm.config.FeCommConfig;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collection;

/**
 * netty服务发布类
 */
@Component
public class FeTcpServer extends BaseServer {
    private static Logger logger = LoggerFactory.getLogger(FeTcpServer.class);
    /**
     * 监听端口
     */
    private static int[] ports = {9035};
    @Autowired
    private FeCommConfig feCommConfig;

    /**
     * 启动服务
     */
    @Override
    public void execute() {

        EventLoopGroup bossGroup = new NioEventLoopGroup();
        // Netty4 默认线程的个数为CPU的核数乘以2
        EventLoopGroup workerGroup = new NioEventLoopGroup(4);
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                    // 存放已完成三次握手的请求的队列的最大长度。如果未设置或所设置的值小于1，使用默认值50
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .option(ChannelOption.SO_RCVBUF, 10240)
                    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000)
                    //保持长连接状态
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childHandler(new FeChannelInitializer());

            Collection<Channel> channels = new ArrayList<>();

            int[] portArray = getPorts(feCommConfig.getPorts());
            if (portArray != null && portArray.length > 0) {
                ports = portArray;
            }
            // 服务绑定到指定端口 线程同步阻塞等待
            Channel serverChannel;
            for (int tmpPort : ports) {
                serverChannel = bootstrap.bind(tmpPort).sync().channel();
                channels.add(serverChannel);
            }

            // 给Channel增加管道关闭的监听器并同步阻塞,直到Channel关闭,线程才会往下执行,结束进程
            for (Channel channel : channels) {
                channel.closeFuture().sync();
            }

        } catch (Exception e) {
            logger.error("start netty server error.", e);
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }

    }

}
